Обзор ERP с открытым исходным кодом (по состоянию на май 2013 года)
Я рассматривал основные продукты с открытым исходным кодом ERP. Я требую, чтобы ERP предоставляла финансовые услуги, продажи, закупки, изготовление/складские и складские функции. Я смотрел на то, что поддерживается в каждой из этих функций, кратко взаимодействуя с их демонстрационными примерами, глядя на их техническую архитектуру высокого уровня и отбирая часть своего исходного кода.
Я надеюсь найти систему, которая не слишком раздута с чрезмерно сложными библиотеками, демонстрирует некоторую иерархию, которая отделяет постоянство, логику домена и презентацию (MVC также не является обязательной), не очень громоздко настраивать или расширять, и что демонстрирует несколько чистую, хорошо продуманную структуру реляционных таблиц. По сути, что-то наполовину между примитивно организованным php или клиентом/сервером и раздутым J2EE. Я также одобряю хорошо спроектированную систему с некоторыми недостатками, отсутствующими в плохо спроектированной системе, которая охватывает все функции, которые мне нужны.
Вопросы, на которые я надеюсь ответить ниже:
- Что там сейчас (с хотя бы некоторым использованием)?
- Что такое достойный набор конкретных функций для системы ERP (и что, вероятно, должно быть отдельным продуктом)?
- Высокоуровневые (предвзятые) реакции на их техническую архитектуру и импульс, окружающий технологический стек.
- Подробный пример из каждой системы, показывающий типичный стиль и организацию кода.
- Первоначальная критика их основной структуры реляционных таблиц
- Активность сообщества, поддержка, импульс?
Ответы
Ответ 1
OpenERP - элегантность и простота. Python, Javascript. Очень хорошо слоистый и модульный, но использует легкие рамки. Только пожелайте, чтобы он не использовал ORM. Tech обзор. Ключевые документы:. Source repos: server, addons, web, или все-в-одном. Ключевые исходные каталоги:/openerp/addons
erpNext - интересный. Python. немного менее модульной, чем OpenERP. Tech зависимости, структура, структура веб-заметок overview. Ключевые документы:. Источник repo и веб-блокнот repo. Ключевые исходные каталоги:
OpenBravo - хорошо слоистые, несколько тяжеловесные фреймворки. Ява. Tech обзор. Ключевые документы:. Источник repo. Ключевые исходные каталоги:/src-db/database/model,/src/erpCommon/[info, ad_process, ad_callouts, ad_actionButtons, ad_forms, ad_reports],/src/org/openbravo/erpReports
opentaps - хорошо слоистые, тяжеловесные рамки. Ява. Tech обзор. Ключевые документы:. Источник repo. Ключевые исходные каталоги:/application/*/[data, entitydef, servicedef, src, scripts, webapp, widget],/opentaps/[crmsfa, финансовые показатели, покупка, склад]
PostBooks - несколько простая реализация, с достойной организацией, но желаю, чтобы у нее было больше слоев. Некоторое приятное использование объектов в GUI-клиенте. Мне не нравится интенсивное использование языка программирования баз данных pgpsql и встроенного sql-кода в клиентском коде. С++, Pgpsql, Javascript. Tech обзор. Ключевые документы:. Источник repo. Основные исходные каталоги:/xtuple/[guiclient, share/reports],/xtuple/[functions, metasql, misc/postbooks_empty.backup, триггеры, типы, представления]
WebERP - действительно простая реализация, предназначенная для любого, кто сможет ее модифицировать. Это также означает, что это не так хорошо слоистое или модульное. Процедурный PHP, без фреймворков. Технический обзор фонды и structure. Ключевые документы:. Источник repo. Ключевые исходные каталоги:/,/includes,/sql/mysql/weberp-new.sql
Ответ 2
Проекты делятся на 4 семьи, некоторые из которых совершенно отделены от семьи.
- Compiere → Adiempiere, OpenBravo, Adaxa, SocrateOpen, A1.io
- TinyERP → OpenERP, Tryton
- WebERP → FrontAccounting
- OFBiz → opentaps
- PostBooks
- ERPNext
(ERP5 выглядел интересным, но мертвым. GnuE может быть интересным, если он набирает обороты. JFire, семейство SQL Ledger просто не хватало, чтобы функции были полноценными ERP)
Помимо списка википедии и отдельных статей продукта, вы можете найти обзоры и списки на следующих сайтах:
Ответ 3
Это похоже на полезный, несколько минимальный набор функций для планирования и обработки пищевых продуктов ERP:
- Бухгалтерский учет/финансы - бухгалтерская книга, a/p, a/r, денежные средства, основные средства, финансовые отчеты, налоги.
- Производство, Склад - заказ на изготовление, изготовление спецификаций материалов, запрос материала, задачи, слежение за последовательными/партиями, упаковка, трансформация изделий/производство
- Инвентарь - получение, отправка, физический инвентарь, товарные позиции, переводы предметов
- Закупки - запрос на покупку, заказ на поставку, отложенные ордера
- Продажи - заказы на продажу, счета-фактуры на продажу
- Планирование запросов материалов - план производства, мастер-график производства, план требований к материалам, плановые заказы
Кажется, что они лучше предоставляются специализированными продуктами или добавляются при необходимости:
- Продажи - все, кроме заказов и счетов-фактур
- Финансовое планирование/анализ
- Планирование запросов материалов - планирование емкости, управление ограничениями
- CRM/Управление услугами/Маркетинг
- Управление проектами
- HR
- Электронная коммерция
- POS
Составлено из обзора:
Ответ 4
Некоторая выборка конструкций таблиц/объектов:
Ledger (некоторые ниже, похоже, используют таблицу строк и записей, некоторые из них не нуждаются в дальнейшем исследовании)
opentaps
AcctgTransEntry
title="Transaction Entry Entity">
acctgTransId" type="id-ne"
acctgTransEntrySeqId" type="id-ne"
acctgTransEntryTypeId" type="id-ne"
description" type="description"
voucherRef" type="short-varchar"
partyId" type="id"
roleTypeId" type="id"
theirPartyId" type="id"
productId" type="id"
theirProductId" type="id"
inventoryItemId" type="id"
glAccountTypeId" type="id"
glAccountId" type="id-ne"
organizationPartyId" type="id-ne"
amount" type="currency-amount"
currencyUomId" type="id"
origAmount" type="currency-amount"
origCurrencyUomId" type="id"
debitCreditFlag" type="indicator"
dueDate" type="date"
groupId" type="id"
taxId" type="id"
reconcileStatusId" type="id"
settlementTermId" type="id"
isSummary" type="indicator"
prim-key acctgTransId
prim-key acctgTransEntrySeqId
type="one" rel-entity-name="AcctgTransEntryType"> acctgTransEntryTypeId"/>
type="one" title="Currency" rel-entity-name="Uom"> <!-- title strictly speaking not necessary here but nice for consistency --> currencyUomId" rel-field-name="uomId"/>
type="one" title="OrigCurrency" rel-entity-name="Uom"> origCurrencyUomId" rel-field-name="uomId"/>
type="one" rel-entity-name="AcctgTrans"> acctgTransId"/>
type="one" rel-entity-name="InventoryItem"> inventoryItemId"/>
type="one" rel-entity-name="Party"> partyId"/>
type="one" rel-entity-name="RoleType"> roleTypeId"/>
type="one-nofk" rel-entity-name="PartyRole"> partyId"/> roleTypeId"/>
type="one" rel-entity-name="GlAccountType"> glAccountTypeId"/>
type="one" rel-entity-name="GlAccount"> glAccountId"/>
type="one" rel-entity-name="GlAccountOrganization"> glAccountId"/> organizationPartyId"/>
type="one" rel-entity-name="StatusItem"> reconcileStatusId" rel-field-name="statusId"/>
type="one" rel-entity-name="SettlementTerm"> settlementTermId"/>
openbravo
GL_JOURNALLINE" primaryKey="GL_JOURNALENTRY_KEY">
GL_JOURNALLINE_ID" primaryKey="true" required="true" type="VARCHAR" size="32"
AD_CLIENT_ID" required="true" type="VARCHAR" size="32"
AD_ORG_ID" required="true" type="VARCHAR" size="32"
ISACTIVE" required="true" type="CHAR" size="1" <default>Y
CREATED" required="true" type="TIMESTAMP" size="7" <default>SYSDATE
CREATEDBY" required="true" type="VARCHAR" size="32"
UPDATED" required="true" type="TIMESTAMP" size="7" <default>SYSDATE
UPDATEDBY" required="true" type="VARCHAR" size="32"
GL_JOURNAL_ID" required="true" type="VARCHAR" size="32"
LINE" required="true" type="DECIMAL" size="10,0"
ISGENERATED" required="true" type="CHAR" size="1" <default>N
DESCRIPTION" type="NVARCHAR" size="255"
AMTSOURCEDR" required="true" type="DECIMAL" <default>0
AMTSOURCECR" required="true" type="DECIMAL" <default>0
C_CURRENCY_ID" required="true" type="VARCHAR" size="32"
CURRENCYRATETYPE" required="true" type="VARCHAR" size="60"
CURRENCYRATE" required="true" type="DECIMAL" <default>0
DATEACCT" type="TIMESTAMP" size="7"
AMTACCTDR" required="true" type="DECIMAL" <default>0
AMTACCTCR" required="true" type="DECIMAL" <default>0
C_UOM_ID" type="VARCHAR" size="32"
QTY" type="DECIMAL" <default>0
C_VALIDCOMBINATION_ID" required="true" type="VARCHAR" size="32"
C_DEBT_PAYMENT_ID" type="VARCHAR" size="32"
C_WITHHOLDING_ID" type="VARCHAR" size="32"
C_TAX_ID" type="VARCHAR" size="32" autoIncrement="false">
USER1_ID" type="VARCHAR" size="32" autoIncrement="false">
USER2_ID" type="VARCHAR" size="32" autoIncrement="false">
C_CAMPAIGN_ID" type="VARCHAR" size="32" autoIncrement="false">
C_PROJECT_ID" type="VARCHAR" size="32" autoIncrement="false">
C_ACTIVITY_ID" type="VARCHAR" size="32" autoIncrement="false">
C_SALESREGION_ID" type="VARCHAR" size="32" autoIncrement="false">
M_PRODUCT_ID" type="VARCHAR" size="32" autoIncrement="false">
C_BPARTNER_ID" type="VARCHAR" size="32" autoIncrement="false">
C_BPARTNER_ID" type="VARCHAR" size="32" autoIncrement="false">
<foreign-key foreignTable="AD_CLIENT" name="GL_JOURNALLINE_AD_CLIENT">
<reference local="AD_CLIENT_ID" foreign="AD_CLIENT_ID"/>
<foreign-key foreignTable="AD_ORG" name="GL_JOURNALLINE_AD_ORG">
<reference local="AD_ORG_ID" foreign="AD_ORG_ID"/>
<foreign-key foreignTable="C_ACTIVITY" name="GL_JOURNALLINE_C_ACTIVITY">
<reference local="C_ACTIVITY_ID" foreign="C_ACTIVITY_ID"/>
<foreign-key foreignTable="C_BPARTNER" name="GL_JOURNALLINE_C_BPARTNER">
<reference local="C_BPARTNER_ID" foreign="C_BPARTNER_ID"/>
<foreign-key foreignTable="C_CAMPAIGN" name="GL_JOURNALLINE_C_CAMPAIGN">
<reference local="C_CAMPAIGN_ID" foreign="C_CAMPAIGN_ID"/>
<foreign-key foreignTable="C_CURRENCY" name="GL_JOURNALLINE_C_CURRENCY">
<reference local="C_CURRENCY_ID" foreign="C_CURRENCY_ID"/>
<foreign-key foreignTable="C_DEBT_PAYMENT" name="GL_JOURNALLINE_C_DEBT_PAYMENT">
<reference local="C_DEBT_PAYMENT_ID" foreign="C_DEBT_PAYMENT_ID"/>
<foreign-key foreignTable="C_PROJECT" name="GL_JOURNALLINE_C_PROJECT">
<reference local="C_PROJECT_ID" foreign="C_PROJECT_ID"/>
<foreign-key foreignTable="C_SALESREGION" name="GL_JOURNALLINE_C_SALESREGION">
<reference local="C_SALESREGION_ID" foreign="C_SALESREGION_ID"/>
<foreign-key foreignTable="C_TAX" name="GL_JOURNALLINE_C_TAX">
<reference local="C_TAX_ID" foreign="C_TAX_ID"/>
<foreign-key foreignTable="C_UOM" name="GL_JOURNALLINE_C_UOM">
<reference local="C_UOM_ID" foreign="C_UOM_ID"/>
<foreign-key foreignTable="C_VALIDCOMBINATION" name="GL_JOURNALLINE_C_VALIDCOMBINAT">
<reference local="C_VALIDCOMBINATION_ID" foreign="C_VALIDCOMBINATION_ID"/>
<foreign-key foreignTable="C_WITHHOLDING" name="GL_JOURNALLINE_C_WITHHOLDING">
<reference local="C_WITHHOLDING_ID" foreign="C_WITHHOLDING_ID"/>
<foreign-key foreignTable="GL_JOURNAL" name="GL_JOURNALLINE_GL_JOURNAL">
<reference local="GL_JOURNAL_ID" foreign="GL_JOURNAL_ID"/>
<foreign-key foreignTable="M_PRODUCT" name="GL_JOURNALLINE_M_PRODUCT">
<reference local="M_PRODUCT_ID" foreign="M_PRODUCT_ID"/>
<check (C_TAX_ID IS NULL) OR (C_WITHHOLDING_ID IS NULL)]]>
<check ISACTIVE IN ('Y', 'N')]]>
<check ISGENERATED IN ('Y', 'N')]]>
postbooks
CREATE TABLE gltrans (
gltrans_id integer DEFAULT nextval(('"gltrans_gltrans_id_seq"'::text)::regclass) NOT NULL,
gltrans_exported boolean,
gltrans_created timestamp with time zone,
gltrans_date date NOT NULL,
gltrans_sequence integer,
gltrans_accnt_id integer NOT NULL,
gltrans_source text,
gltrans_docnumber text,
gltrans_misc_id integer,
gltrans_amount numeric(20,2) NOT NULL,
gltrans_notes text,
gltrans_journalnumber integer,
gltrans_posted boolean NOT NULL,
gltrans_doctype text,
gltrans_rec boolean DEFAULT false NOT NULL,
gltrans_username text DEFAULT geteffectivextuser() NOT NULL,
gltrans_deleted boolean DEFAULT false
);
openerp
_columns = {
'name': fields.char('Number', size=64, required=True),
'ref': fields.char('Reference', size=64),
'period_id': fields.many2one('account.period', 'Period', required=True, states={'posted':[('readonly',True)]}),
'journal_id': fields.many2one('account.journal', 'Journal', required=True, states={'posted':[('readonly',True)]}),
'state': fields.selection([('draft','Unposted'), ('posted','Posted')], 'Status', required=True, readonly=True)
'line_id': fields.one2many('account.move.line', 'move_id', 'Entries', states={'posted':[('readonly',True)]}),
'to_check': fields.boolean('To Review', ),
'partner_id': fields.related('line_id', 'partner_id', type="many2one", relation="res.partner", string="Partner", store=True),
'amount': fields.function(_amount_compute, string='Amount', digits_compute=dp.get_precision('Account'), type='float', fnct_search=_search_amount),
'date': fields.date('Date', required=True, states={'posted':[('readonly',True)]}, select=True),
'narration':fields.text('Internal Note'),
'company_id': fields.related('journal_id','company_id',type='many2one',relation='res.company',string='Company', store=True, readonly=True),
'balance': fields.float('balance', digits_compute=dp.get_precision('Account')),
}
_defaults = {
'name': '/',
'state': 'draft',
'period_id': _get_period,
'date': fields.date.context_today,
'company_id': lambda self, cr, uid, c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.id,
}
weberp
CREATE TABLE `gltrans` (
`counterindex` int(11) NOT NULL AUTO_INCREMENT,
`type` smallint(6) NOT NULL DEFAULT '0',
`typeno` bigint(16) NOT NULL DEFAULT '1',
`chequeno` int(11) NOT NULL DEFAULT '0',
`trandate` date NOT NULL DEFAULT '0000-00-00',
`periodno` smallint(6) NOT NULL DEFAULT '0',
`account` varchar(20) NOT NULL DEFAULT '0',
`narrative` varchar(200) NOT NULL DEFAULT '',
`amount` double NOT NULL DEFAULT '0',
`posted` tinyint(4) NOT NULL DEFAULT '0',
`jobref` varchar(20) NOT NULL DEFAULT '',
`tag` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`counterindex`),
KEY `Account` (`account`),
KEY `ChequeNo` (`chequeno`),
KEY `PeriodNo` (`periodno`),
KEY `Posted` (`posted`),
KEY `TranDate` (`trandate`),
KEY `TypeNo` (`typeno`),
KEY `Type_and_Number` (`type`,`typeno`),
KEY `JobRef` (`jobref`),
KEY `tag` (`tag`),
KEY `tag_2` (`tag`),
KEY `tag_3` (`tag`),
KEY `tag_4` (`tag`),
FOREIGN KEY (`account`) REFERENCES `chartmaster` (`accountcode`),
FOREIGN KEY (`type`) REFERENCES `systypes` (`typeid`),
FOREIGN KEY (`periodno`) REFERENCES `periods` (`periodno`)
)
erpnext
РО