feat(tahesab): net sales by factor, group, and commission
Report weight after returns for the selected period, with parent customer groups and separate silver and investment commission. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import { describe, it } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import {
|
||||
classifyDirection,
|
||||
classifyFactor,
|
||||
movementStats,
|
||||
type SalesDoc,
|
||||
} from '../src/integrations/tahesab/sales-factors';
|
||||
|
||||
function doc(partial: Partial<SalesDoc> & Pick<SalesDoc, 'direction' | 'weight'>): SalesDoc {
|
||||
return {
|
||||
bucketKey: 'A',
|
||||
factor: 'karsakhte',
|
||||
mali: 0,
|
||||
count: 0,
|
||||
percent: null,
|
||||
tarikh: '1405-01-01',
|
||||
...partial,
|
||||
};
|
||||
}
|
||||
|
||||
describe('classify', () => {
|
||||
it('مرجوعی کارساخته را قبل از ورود و خروج تشخیص میدهد', () => {
|
||||
assert.equal(classifyDirection('ورود کارساخته مرجوعی'), 'sale_return');
|
||||
assert.equal(classifyDirection('خروج کارساخته مرجوعی'), 'purchase_return');
|
||||
assert.equal(classifyDirection('ورود کارساخته'), 'in');
|
||||
assert.equal(classifyDirection('خروج کارساخته'), 'out');
|
||||
});
|
||||
|
||||
it('شمش و جواهر و اتیکت را جدا میکند', () => {
|
||||
assert.equal(classifyFactor('فروش', 'شمش نقره'), 'bullion');
|
||||
assert.equal(classifyFactor('فروش اتیکت جواهر', null), 'etiket_jewel');
|
||||
assert.equal(classifyFactor('فروش اتیکت', 'طلا'), 'etiket_gold');
|
||||
assert.equal(classifyFactor('خروج کارساخته', 'نگین'), 'karsakhte');
|
||||
});
|
||||
});
|
||||
|
||||
describe('movementStats', () => {
|
||||
it('فروش کامل مرجوعشده از آمار فروش خارج و در مرجوعی میماند', () => {
|
||||
const stats = movementStats(
|
||||
[
|
||||
doc({ direction: 'out', weight: 10, mali: 100, percent: 5, tarikh: '1405-01-01' }),
|
||||
doc({ direction: 'sale_return', weight: 10, mali: 100, percent: 5, tarikh: '1405-01-02' }),
|
||||
],
|
||||
'out',
|
||||
);
|
||||
assert.equal(stats.grossWeight, 10);
|
||||
assert.equal(stats.returnWeight, 10);
|
||||
assert.equal(stats.netWeight, 0);
|
||||
assert.equal(stats.netMali, 0);
|
||||
assert.equal(stats.percent, null);
|
||||
});
|
||||
|
||||
it('مرجوعی جزئی فقط همان وزن را از میانگین درصد کم میکند', () => {
|
||||
const stats = movementStats(
|
||||
[
|
||||
doc({ direction: 'out', weight: 10, percent: 4, tarikh: '1405-01-01' }),
|
||||
doc({ direction: 'out', weight: 10, percent: 8, tarikh: '1405-01-10' }),
|
||||
doc({ direction: 'sale_return', weight: 10, tarikh: '1405-01-11' }),
|
||||
],
|
||||
'out',
|
||||
);
|
||||
assert.equal(stats.netWeight, 10);
|
||||
assert.equal(stats.percent?.avg, 4);
|
||||
assert.equal(stats.percent?.first, 4);
|
||||
assert.equal(stats.percent?.last, 4);
|
||||
});
|
||||
|
||||
it('میانگین درصد وزنی است', () => {
|
||||
const stats = movementStats(
|
||||
[
|
||||
doc({ direction: 'in', weight: 10, percent: 2, tarikh: '1405-01-01' }),
|
||||
doc({ direction: 'in', weight: 30, percent: 6, tarikh: '1405-02-01' }),
|
||||
],
|
||||
'in',
|
||||
);
|
||||
assert.equal(stats.percent?.first, 2);
|
||||
assert.equal(stats.percent?.last, 6);
|
||||
assert.equal(stats.percent?.min, 2);
|
||||
assert.equal(stats.percent?.max, 6);
|
||||
assert.equal(stats.percent?.avg, 5);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user